# 存放第三放扣扣登陆的工具文件
import json
from urllib.parse import urlencode, parse_qs
from urllib.request import urlopen

import logging
from django.conf import settings
from itsdangerous import TimedJSONWebSignatureSerializer as TJWSSerializer, BadData

from oauth.exceptions import OAuthQQAPIError

logger = logging.getLogger('django')


class OAuthQQ():
    def __init__(self, client_id=None, redirect_uri=None, state=None, client_secret=None):
        self.state = state or settings.QQ_STATE
        self.client_id = client_id or settings.QQ_CLIENT_ID
        self.redirect_uri = redirect_uri or settings.QQ_REDIRECT_URI
        self.client_secret = client_secret or settings.QQ_CLIENT_SECRET

    def get_oauth_url(self):
        url = 'https://graph.qq.com/oauth2.0/authorize?'

        data = {
            'response_type': 'code',
            'client_id': self.client_id,
            'redirect_uri': self.redirect_uri,
            'state': self.state
        }

        url += urlencode(data)

        return url

    def get_access_token(self, code):
        url = 'https://graph.qq.com/oauth2.0/token?'

        data = {
            'grant_type': 'authorization_code',
            'client_id': self.client_id,
            'client_secret': self.client_secret,
            'code': code,
            'redirect_uri': self.redirect_uri
        }

        url += urlencode(data)
        try:
            # 服务器向第三方服务器发送请求 获取access_token
            response = urlopen(url)
            # read获取请求返回的响应里的响应体
            response_data = response.read().decode()
            # parse_qs把响应体的里面的数据转换为字典
            msg = parse_qs(response_data)
            # 从转换的字典里面取出access_token 取出的是个列表
        except Exception as e:
            logger.error(e)
            raise OAuthQQAPIError
        else:
            access_token = msg['access_token']

        return access_token[0]

    def get_openid(self, access_token):
        url = 'https://graph.qq.com/oauth2.0/me?access_token=' + access_token

        try:
            # 发送请求
            resp = urlopen(url)
            # 读取响应体数据
            resp_data = resp.read()  # bytes
            resp_data = resp_data.decode()  # str
            # callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} )\n;
            # 解析
            resp_data = resp_data[10:-4]
            resp_dict = json.loads(resp_data)
        except Exception as e:
            logger.error('获取openid异常：%s' % e)
            raise OAuthQQAPIError
        else:
            openid = resp_dict.get('openid')
            return openid

    def generate_save_user_token(self,openid):
        serializer = TJWSSerializer(settings.SECRET_KEY, 300)
        token = serializer.dumps({'openid': openid})
        return token.decode()

    @staticmethod
    def check_save_user_token(token):
        """
        检验保存用户数据的token
        :param token: token
        :return: openid or None
        """
        serializer = TJWSSerializer(settings.SECRET_KEY, 300)
        try:
            data = serializer.loads(token)
        except BadData:
            return None
        else:
            return data.get('openid')